`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////
////                                                              //// 
////                                                              //// 
////  Part of the project chess controller                        ////  
////                                                              ////
////                                                              //// 
////  Description                                                 //// 
////   -                                 //// 
////                                                              //// 
////  To Do:                                                      //// 
////   -                                //// 
////                                                              //// 
////  Author(s):                                                  //// 
////      - Sergio Gonzalez Q, sergiogq@hotmail.es                ////
////      - Alejandro Morales A, ale3191@gmail.com                //// 
////                                                              //// 
////////////////////////////////////////////////////////////////////// 
////                                                              //// 
//// Copyright (C) 2009 Authors and OPENCORES.ORG                 //// 
////                                                              //// 
//// This source file may be used and distributed without         //// 
//// restriction provided that this copyright statement is not    //// 
//// removed from the file and that any derivative work contains  //// 
//// the original copyright notice and the associated disclaimer. //// 
////                                                              //// 
//// This source file is free software; you can redistribute it   //// 
//// and/or modify it under the terms of the GNU Lesser General   //// 
//// Public License as published by the Free Software Foundation; //// 
//// either version 2.1 of the License, or (at your option) any   //// 
//// later version.                                               //// 
////                                                              //// 
//// This source is distributed in the hope that it will be       //// 
//// useful, but WITHOUT ANY WARRANTY; without even the implied   //// 
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //// 
//// PURPOSE.  See the GNU Lesser General Public License for more //// 
//// details.                                                     //// 
////                                                              //// 
//// You should have received a copy of the GNU Lesser General    //// 
//// Public License along with this source; if not, download it   //// 
//// from http://www.opencores.org/lgpl.shtml                     //// 
////                                                              ////
//////////////////////////////////////////////////////////////////////

//La mquina de estados Finitos se encarga de realizar todo el control 

// Definicion del modulo
module FSM_Board_Reader( 
    input _system_clk_i,
	 input _rst_i,
	 input _board_checking_clk_i,
	 output reg [7:0] columnLED_o,
	 output reg [63:0] chessboard_snapshot_o, 
    output reg send_data_o,
    input data_sent_i, 
	 input row0_i, row1_i, row2_i, row3_i, row4_i, row5_i, row6_i, row7_i, 
	 output reg [7:0] column_o,
	 output reg [3:0] columnCounter_o,
	 output reg [3:0] rowCounter_o,
	 output reg [3:0] pos_o,
	 output reg empty_o
 );
 
 //definicion de estados de la maquina
	localparam start = 2'b00;
	localparam check_chessboard = 2'b01;
	localparam send_chessboard_snapshot = 2'b10;

	wire row0,row1, row2, row3, row4, row5, row6, row7;

	assign row0 = row0_i;
	assign row1 = row1_i;
	assign row2 = row2_i;
	assign row3 = row3_i;
	assign row4 = row4_i;
	assign row5 = row5_i;
	assign row6 = row6_i;
	assign row7 = row7_i;


	reg [3:0] columnCounter;
   reg [3:0] rowCounter;
	reg [63:0] chessboard_snapshot;
	reg [3:0] pos;
   
	//estado actual y siguiente
	reg [1:0] presentState;
	//reg [1:0] nextState;

		
	//transition logic
	always @(posedge _system_clk_i) begin
		
		if(_rst_i == 1) begin
			presentState = start;
		end
		else begin
		
			case(presentState)
			
				//estado inicial
				start:begin
					rowCounter = 0;
					columnCounter = 0;
					pos_o = 0;
					pos = 0;
					chessboard_snapshot = 0;
					presentState = check_chessboard;
				end

				//lee el tablero
				check_chessboard:begin
					pos_o = pos;
					if(rowCounter == 8)//8
						begin
							rowCounter = 0;
							presentState = send_chessboard_snapshot;
						end
			 
					else if(columnCounter == 8)//8
						 begin
								 columnCounter = 0;
								 rowCounter =  rowCounter + 1;
						 end
					else				
						begin
							if (_board_checking_clk_i)
								begin
									case(rowCounter)
									
									0:begin
										chessboard_snapshot[0]= row0;
										if (columnCounter < 4)
											pos = pos + 1;
										empty_o = ~row0;
										chessboard_snapshot = chessboard_snapshot << 1;
									end
									
									1:begin
										chessboard_snapshot[0] = row1;
										if (columnCounter < 4)
											pos = pos + 1;
										empty_o = ~row1;
										chessboard_snapshot = chessboard_snapshot << 1;
									end
									
									2:begin
										chessboard_snapshot[0] = row2;
										if (columnCounter < 4)
											pos = pos + 1;
										empty_o = ~row2;
										chessboard_snapshot = chessboard_snapshot << 1;
									end
									
									3:begin
										chessboard_snapshot[0] = row3;
										if (columnCounter < 4)
											pos_o = pos_o + 1;
										empty_o = ~row3;
										chessboard_snapshot = chessboard_snapshot << 1;
									end
									4:begin
										chessboard_snapshot[0] = row4;
										chessboard_snapshot = chessboard_snapshot << 1;
									end	
									5:begin
										chessboard_snapshot[0] = row5;
										chessboard_snapshot = chessboard_snapshot << 1;
									end	
									6:begin
										chessboard_snapshot[0] = row6;
										chessboard_snapshot = chessboard_snapshot << 1;
									end	
									7:begin
										chessboard_snapshot[0] = row7;
										if(columnCounter < 7)
										begin
											chessboard_snapshot = chessboard_snapshot << 1;
										end
									end
									default:begin
										chessboard_snapshot[0] = row0;
								  end
								  
								  endcase
								  
								  columnCounter = columnCounter + 1;
								  
								end
						end
				end
				
				//envia una seal a Facade para que envie la matriz que
				//representa al tablero hacia la computadora.			
				send_chessboard_snapshot:begin
					if(data_sent_i == 1)
					begin
						presentState = start;
					end		
				end
				
				default begin
					presentState = start;
				end
				
			endcase
		end
	end

	
	//outputs
	always @(posedge _system_clk_i) begin
		case(presentState)
		
			start: begin
				 chessboard_snapshot_o = 0;
			    send_data_o = 0; 
				 column_o = 8'b00000000;
				 columnLED_o = 8'b00000000;
				 rowCounter_o = 0;
	          columnCounter_o = 0;
			end
			
			check_chessboard: begin
				chessboard_snapshot_o = chessboard_snapshot;
				send_data_o = 0;
				rowCounter_o = rowCounter;
	         columnCounter_o = columnCounter;		
				if(columnCounter == 7)
				begin
					columnLED_o [7:0] = chessboard_snapshot_o[7:0];
				end	
				 
			   case(columnCounter)
				   0:begin
					  column_o = 8'b00000001;
					end
				   1:begin
					  column_o = 8'b00000010;
					end
				   2:begin
					  column_o = 8'b00000100;
					end
					3:begin
					  column_o = 8'b00001000;
					end
				   4:begin
					  column_o = 8'b00010000;
					end	
				   5:begin
					  column_o = 8'b00100000;
					end	
				   6:begin
					  column_o = 8'b01000000;
					end	
				   7:begin
					  column_o = 8'b10000000;
					end
					default:begin
					  column_o = 8'b00000000;
				  end		
			   endcase	
		   end
			
			send_chessboard_snapshot: begin
				 chessboard_snapshot_o = chessboard_snapshot;
				 columnLED_o = 8'b11111111;
				 send_data_o = 1;
				 column_o = 8'b00000000;
				 rowCounter_o = 0;
	          columnCounter_o = 0;
			 end	
				 
			default begin
				 chessboard_snapshot_o = 0;
				 send_data_o = 0;
				 column_o = 8'b00000000;
 			    columnLED_o = 8'b00000000;
				 rowCounter_o = 0;
	          columnCounter_o = 0;
			end
			
		endcase
	end	
endmodule
